package com.hrhr74.penguinstream.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hrhr74.penguinstream.constant.AddressConstant;
import com.hrhr74.penguinstream.domain.dto.AddressDTO;
import com.hrhr74.penguinstream.domain.po.Address;
import com.hrhr74.penguinstream.domain.vo.AddressVO;
import com.hrhr74.penguinstream.exception.AddressException;
import com.hrhr74.penguinstream.mapper.AddressMapper;
import com.hrhr74.penguinstream.service.IAddressService;
import com.hrhr74.penguinstream.utils.Result;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements IAddressService {

    private final StringRedisTemplate  stringRedisTemplate;
    /**
     * 新增地址
     *
     * @param addressDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result saveAddress(AddressDTO addressDTO) {
        Long userId = 1L;//TODO UserContext.getUser();

        if(userId == null){
            return Result.error("新增失败！");
        }

        if(addressDTO == null){
            return Result.error("新增地址失败！");
        }

        if(lambdaQuery().eq(Address::getUserId,userId).count() > AddressConstant.maxAddressNum){
            return Result.error("当前用户的地址数量已达最大值" + AddressConstant.maxAddressNum +"，不能再增加地址！");
        }

        if(addressDTO.getIsDefault()){
            //将所有地址设置为非默认地址
            boolean update = lambdaUpdate().set(Address::getIsDefault, false)
                    .eq(Address::getUserId, userId).update();
        }

        Address address = BeanUtil.copyProperties(addressDTO, Address.class);
        address.setUserId(userId);
        address.setCreateTime(LocalDateTime.now());
        address.setUpdateTime(LocalDateTime.now());
        boolean save = save(address);
        return save ? Result.ok("新增地址成功！"): Result.error("新增地址失败！");
    }

    /**
     * 查询用户地址
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public Result<List<AddressVO>> listAddress(Long userId) {
        if(userId == null){
            return Result.error("当前用户未登录！");
        }

        List<Address> list = lambdaQuery().eq(Address::getUserId, userId)
                .orderByDesc(Address::getIsDefault)
                .orderByDesc(Address::getUpdateTime)
                .list();
        if(list.isEmpty()){
            return Result.ok(Collections.emptyList(),"查询成功，当前没有地址");
        }

        List<AddressVO> addressVOS = BeanUtil.copyToList(list, AddressVO.class);
        return Result.ok(addressVOS,"查询成功");
    }

    /**
     * 修改地址
     * @param addressDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateAddress(AddressDTO addressDTO) {
        Long userId = 1L;//TODO UserContext.getUser();
        if(addressDTO == null){
            return Result.error("请输入正确的修改信息");
        }

        if(addressDTO.getIsDefault()){
            lambdaUpdate().set(Address::getIsDefault, false).eq(Address::getUserId, userId).ne(Address::getId,addressDTO.getId()).update();
            //将当前的地址写入redis
            writeAddressToRedis(userId);
        }

        Address address = BeanUtil.copyProperties(addressDTO, Address.class);
        boolean update = updateById(address);
        return update ?Result.ok("修改成功") : Result.error("修改失败！");
    }


    /**
     * 设置默认
     * @param addressId
     * @return
     */
    @Override
    @Transactional
    public Result setDefault(Long addressId) {
        Long userId = 1L;//TODO UserContext.getUser()
        if(userId == null){
            return Result.error("用户未登录！");
        }

        if(addressId == null || !lambdaQuery().eq(Address::getId,addressId).exists()){
            return Result.error("地址信息异常");
        }

        Address id = getById(addressId);
        if(id.getIsDefault()){
            return Result.ok("当前地址已经是默认地址了");
        }

        try {
            //将当前用户所有的地址设置为非默认地址
            lambdaUpdate().set(Address::getIsDefault, false).eq(Address::getUserId, userId).update();


            boolean update = lambdaUpdate().set(Address::getIsDefault, true).eq(Address::getId, addressId).update();
            //将默认地址写入redis
           writeAddressToRedis(userId);

            return update ? Result.ok("当前地址已设置为默认地址！") : Result.error("设置失败！");
        }catch (AddressException e){
           throw new AddressException("更新失败！");
        }
    }

    /**
     * 删除地址
     * @param addressId
     * @return
     */
    @Override
    public Result deleteById(Long addressId) {
        if(addressId == null){
            return Result.error("要删除的地址已删除或不存在！");
        }

        //查询要删除地址是否是默认地址
        Boolean isDefault = getById(addressId).getIsDefault();
        if(isDefault){
            return Result.error("默认地址不能删除！");
        }

        boolean b = removeById(addressId);
        return b ? Result.ok("删除成功！"): Result.error("删除失败！");
    }

    /**
     * 获取默认地址
     * @return
     */
    @Override
    public Result<AddressVO> getDefaultAddress() {
        Long userId = 1L;//TODO UserContext.getUser();
        if(userId == null) {
            return Result.error("当前用户未登录");
        }
        //先从redis获取
        String s = stringRedisTemplate.opsForValue().get(AddressConstant.ADDRESS_KEY + userId);
        if(s != null){

            return Result.ok(JSONUtil.toBean(s,AddressVO.class),"默认地址查询成功");
        }else {

            Address address = lambdaQuery().eq(Address::getUserId, userId)
                    .eq(Address::getIsDefault, true)
                    .one();
            //写入redis
            writeAddressToRedis(userId);
            AddressVO addressVO = BeanUtil.copyProperties(address, AddressVO.class);
            return Result.ok(addressVO, "默认地址查询成功");
        }
    }

    private void writeAddressToRedis(Long userId){
        Address address = lambdaQuery().eq(Address::getUserId, userId).eq(Address::getIsDefault, true).one();
        String key = AddressConstant.ADDRESS_KEY + userId;
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(address));
    }
}
